/*
   k74, kitsrus.com kit 74 parallel port relay driver
   Copyright (C) 2000  James Cameron (quozl@us.netrek.org)

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define K74_VERSION "2.0"

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include "parport.h"

int fd = -1; /* not open */

void port_open_fail(char *name)
{
    char *s;

    if (errno == ENOENT) {
        fprintf(stderr, "k74: you may need to modprobe the ppdev kernel module\n");
    }
    asprintf(&s, "k74: unable to open %s (%d)", name, errno);
    perror(s);
    free(s);
}

void port_open(int port)
{
    char *name;

    asprintf(&name, "/dev/parport%d", port);
    fd = open(name, O_RDWR);
    if (fd < 0) port_open_fail(name);
    free(name);
    if (fd < 0) exit(1);
}

void port_close()
{
    close(fd);
    fd = -1;
}

void _port_write(int port, unsigned char byte)
{
    int s;

    if (fd < 0) port_open(port);
    if (fd < 0) return;
    s = ioctl(fd, PPCLAIM);
    if (s < 0) { perror("ioctl PPCLAIM"); return; }
    s = ioctl(fd, PPWDATA, &byte);
    if (s < 0) { perror("ioctl PPWDATA"); }
    s = ioctl(fd, PPRELEASE);
    if (s < 0) { perror("ioctl PPRELEASE"); }
}

unsigned char _port_read(int port)
{
    unsigned char byte;
    int s;

    if (fd < 0) port_open(port);
    if (fd < 0) return 0;
    s = ioctl(fd, PPCLAIM);
    if (s < 0) { perror("ioctl PPCLAIM"); return 0; }
    s = ioctl(fd, PPRDATA, &byte);
    if (s < 0) { perror("ioctl PPWDATA"); }
    s = ioctl(fd, PPRELEASE);
    if (s < 0) { perror("ioctl PPRELEASE"); }
    return byte;
}

static void copyright()
{
    fprintf(stderr, "Kit 74 Parallel Port Relay Driver, %s\n"
            "Copyright (C) 2000  James Cameron (quozl@us.netrek.org)\n"
            "\n"
            "This program comes with ABSOLUTELY NO WARRANTY; for details see source.\n"
            "This is free software, and you are welcome to redistribute it under certain\n"
            "conditions; see source for details.\n\n", K74_VERSION);
}

static void usage()
{
    copyright();

    fprintf(stderr,
            "Usage: k74 [options] [bit] [command] ...\n"
            "\n"
            "Options\n"
            "    -v  --verbose     issue copyright statement during operation\n"
            "    -V  --version     display version information\n"
            "    -h  --help        display program usage information\n"
            "    -p  --port n      set parallel port for next operation (0,1,2)\n"
            "                      (n may also be 0x378, 0x278, or 0x3bc)\n"
            "Bits\n"
            "    n                 bit number, zero through seven\n"
            "    all               all bits, mask 0xff\n"
            "    lower             lower half of byte, mask 0x0f\n"
            "    upper             upper half of byte, mask 0xf0\n"
            "\n"
            "Commands\n"
            "    set               set the bits\n"
            "    clear             clear the bits\n"
            "    toggle            change the state of the bits\n"
            "    write n           write decimal number n to the port\n"
            "    read              read the port and print on stdout in decimal\n"
            "    watch             continuous read and report changes\n"
            "\n"
            "Examples\n"
            "    # k74 all set                (turns on all bits)\n"
            "    # k74 6 clear                (turns off bit six)\n"
            );

}
